

import 'reflect-metadata'
//校验属性类型赋值正确
const RR=Reflect as any;
const REQUIRED_KEY=Symbol()
const VALIDATE_TYPE_KEY=Symbol()
enum Type{
    String='string',
    Number='number'
}
function Required(){
    return function(target:Object,key:any){
        //把需要必填的属性，记录下来，校验的时候找到这些属性是否有值
        const requiredKeys:string[]=RR.getMetadata(REQUIRED_KEY,target) || []
        RR.defineMetadata(REQUIRED_KEY,[...requiredKeys,key],target)
    }
}
function ValueType(type:Type){
    return function(target:Object,key:any){
//获取当前的属性类型
    RR.defineMetadata(VALIDATE_TYPE_KEY,type,target,key)
    }
}
class Person{
    @ValueType(Type.String)
    @Required()
    name!:string
    @ValueType(Type.Number)
    @Required()
    age!:number

}
function validate(instance:any){
    let existsKeys=RR.ownKeys(instance)
    const requiredKeys=RR.getMetadata(REQUIRED_KEY,instance)
    console.log(33,existsKeys);
    for (const key of requiredKeys) {
        //获取属性对应的类型，用来校验这个类型是否满足
        const validate_type=RR.getMetadata(VALIDATE_TYPE_KEY,instance,key)
        console.log(3333,validate_type);
        if(validate_type){
            if(typeof instance[key]!==validate_type){
                throw new Error(`${key}属性类型不正确`)
            }
        }
        if(!existsKeys.includes(key)){
            throw new Error(`${key}没有传递`)
        }
    }
    

}
const person=new Person();
person.name='xhm'
//@ts-ignore
person.age='12'
validate(person)
//@ts-ignore：不管有没有错误，我都不管，丧失校验
//!@ts-expect-error：我确定下一行是报错的，但是不会显示错误
//@ts-nocheck：放在文件顶部，丧失对此文件的全部校验
//@ts-checkjsdoc来使用的
console.log(1000,RR);
